package com.tju.resource.business.qr;

import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.tju.resource.annotation.Log;
import com.tju.resource.common.ServiceException;
import com.tju.resource.redis.RedisService;
import com.tju.resource.result.Result;
import com.tju.resource.result.ResultEnum;
import com.tju.resource.result.ResultUtil;
import com.tju.resource.tool.enum_utils.FunctionType;
import com.tju.resource.tool.tool.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mobile.device.Device;
import org.springframework.stereotype.Service;

import java.util.Optional;

/**
 * 扫码业务
 *
 * @Author CLS
 * @Date 2022/4/1 13:40
 */
@Service
public class ScanCodeServiceImpl implements ScanCodeService {

    @Autowired
    private RedisService redisService;
    @Autowired
    private ChineseExceptionUtils zh_ch;

    /**
     * 二维码格式：设备，开始日期时间戳，有效时间（1分钟），唯一标识码
     *
     * @param device
     * @return
     */
    @Override
    public String qr(Device device) {
        String uuid = UuidUtils.uniqueCode();
        String qr = "device:" + PublicTools.deviceMatch(device) + ",startDate:" + DateUtil.current() + ",effectiveTime:1min,instruction:" + uuid;
        redisService.setData(uuid, qr, 60);
        return qr;
    }

    /**
     * 第二步：移动端扫码验证二维码是否匹配
     *
     * @return
     */
    @Override
    public Result<Object> scanCodeOnMobile(String qrCodeData) {
        try {
            JSONObject json = JSONUtil.parseObj("{" + qrCodeData + "}");
            String code = (String) redisService.get(json.get("instruction").toString());
            return Optional.ofNullable(code)
                    .filter(c -> c.equals(qrCodeData))
                    .map(q -> {
                        redisService.setData(json.get("instruction").toString(), Constants.Succeed, 60);
                        return ResultUtil.success(ResultEnum.SUCCESS, "扫码成功");
                    })
                    .orElseThrow(() -> new ServiceException(zh_ch.QRCodeExpired));
        } catch (Exception e) {
            throw new ServiceException(zh_ch.QRCodeExpired);
        }
    }


    /**
     * 第四步：移动端确认网页端登录
     *
     * @param token
     * @return
     */
    @Override
    @Log(type = FunctionType.ConfirmLogin)
    public Result<Object> confirmWebLogin(String token, String qrCodeData) {
        try {
            JSONObject json = JSONUtil.parseObj("{" + qrCodeData + "}");
            String cd = (String) redisService.get(json.get("instruction").toString());
            if (EmptyUtils.isEmpty(cd))
                throw new ServiceException(zh_ch.ThisOperationIsInvalid);
            redisService.setData(json.get("instruction").toString(), Constants.Prefix + token, 60);
            return ResultUtil.success(ResultEnum.SUCCESS);
        } catch (Exception e) {
            throw new ServiceException(zh_ch.ThisOperationIsInvalid);
        }
    }


    /**
     * 第三步：网页端轮询验证是否扫码成功
     *
     * @return
     */
    @Override
    public Result<Object> pollingQRCode(String qrCodeData) {
        try {
            JSONObject json = JSONUtil.parseObj("{" + qrCodeData + "}");
            String cd = (String) redisService.get(json.get("instruction").toString());
            if (cd.equals(Constants.Succeed)) {
                return ResultUtil.success(ResultEnum.SPECIAL);
            } else if (cd.startsWith(Constants.Prefix)) {
                redisService.del(json.get("instruction").toString());
                return ResultUtil.success(ResultEnum.SUCCESS, cd.substring(20));
            }
            throw new ServiceException(zh_ch.noGo);
        } catch (Exception e) {
            throw new ServiceException(zh_ch.noGo);
        }
    }

}
